/**
 * 
 */
package io.gitee.falllee.dao.core.table;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.calcite.linq4j.Linq4j;
import org.apache.ibatis.cursor.Cursor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import io.gitee.falllee.common.page.PageRows;
import io.gitee.falllee.dao.cache.DataCache;
import io.gitee.falllee.dao.config.DaoSourceContextHolder;
import io.gitee.falllee.dao.core.BaseBuilder;
import io.gitee.falllee.dao.enums.DataSourceEnum;
import io.gitee.falllee.dao.enums.QueryModeEnum;
import io.gitee.falllee.dao.model.DaoConst;
import io.gitee.falllee.dao.model.DaoException;
import io.gitee.falllee.dao.persistence.DataMapper;
import io.gitee.falllee.dao.util.CommonUtils;
import io.gitee.falllee.dao.util.FilterPlus;
import io.gitee.falllee.common.util.LogUtils;

/**
 * @author batty
 * @date 2022-06-27
 *
 */
public class SelectBuilder extends BaseBuilder {

    private DataCache dataCache;
    
    private DataMapper dataMapper;
    
    private String tableName;

    /**
     * 主键字段
     */
    private String keyField;
    
    /**
     * 查询字段，以,隔开，默认查全部
     */
    private String selectFields;
    
    private boolean enableCache;
    
    /**
     * 原子缓存时间，默认一天
     */
    private Long expireTime;
    
    /**
     * 列表缓存时间，默认半小时
     */
    private Long expireTimeList;

    SelectBuilder(TableBuilder parent) {
        super(parent.getDaoConfig());
        this.dataCache = parent.getDataCache();
        this.dataMapper = parent.getDataMapper();
        this.tableName = parent.getTableName();
        this.keyField = parent.getKeyField();
        this.enableCache = parent.cacheBuilder().enableCache();
        this.expireTime = parent.getExpireTime();
        this.expireTimeList = parent.getExpireTimeList();
    }
    
    public SelectBuilder selectFields(String selectFields) {
        this.selectFields = selectFields;
        return this;
    }

    public SelectFieldBuilder field(String filedName) {
        return new SelectFieldBuilder(this, daoConfig, filedName);
    }

    public SelectMultiFieldBuilder multiField() {
        return new SelectMultiFieldBuilder(this, daoConfig);
    }

    public SelectFilterBuilder filter(FilterPlus filter) {
        return new SelectFilterBuilder(this, daoConfig, filter);
    }

    public SelectCountBuilder count(FilterPlus filter) {
        return new SelectCountBuilder(this, daoConfig, filter);
    }

    public SelectGroupBuilder group(FilterPlus filter, String field, String group) {
        return new SelectGroupBuilder(this, daoConfig, filter, field, group);
    }

    public <V> SelectMinBuilder<V> min(FilterPlus filter, String field, Class<V> clazzV) {
        return new SelectMinBuilder<>(this, daoConfig, filter, field, clazzV);
    }

    public <V> SelectMaxBuilder<V> max(FilterPlus filter, String field, Class<V> clazzV) {
        return new SelectMaxBuilder<>(this, daoConfig, filter, field, clazzV);
    }

    public <V> SelectSumBuilder<V> sum(FilterPlus filter, String field, Class<V> clazzV) {
        return new SelectSumBuilder<>(this, daoConfig, filter, field, clazzV);
    }

    public <V> SelectDistinctBuilder<V> distinct(FilterPlus filter, String field, Class<V> clazzV) {
        return new SelectDistinctBuilder<>(this, daoConfig, filter, field, clazzV);
    }

    public Map<String, Object> selectByKey(Object keyValue) {
        // 如果启用缓存，先从缓存取数据
        if (enableCache) {
            Map<String, Object> t = dataCache.getTableByKeyValue(keyValue, tableName);
            if (t != null) {
                DaoSourceContextHolder.setDaoSource(DataSourceEnum.CACHE.getSource());
                return convertMap(t);
            }
        }
        Map<String, Object> mapResult = selectByKeyValue(keyValue);
        // 如果启用缓存，则写入缓存数据
        if (enableCache) {
            dataCache.setTableByKeyValue(keyValue, mapResult, tableName, expireTime);
        }
        DaoSourceContextHolder.setDaoSource(DataSourceEnum.DB.getSource());
        return convertMap(mapResult);
    }

    private Map<String, Object> selectByKeyValue(Object keyValue) {
        Map<String, Object> map = new HashMap<>(16);
        if (!StringUtils.hasLength(tableName)) {
            throw new DaoException("table name cannot be null");
        }
        map.put(DaoConst.TABLE_NAME, tableName);
        if (!StringUtils.hasLength(keyField)) {
            throw new DaoException("key field cannot be null");
        }
        keyField = getQuoteField(keyField);
        map.put(DaoConst.KEY_FIELD, keyField);
        if (ObjectUtils.isEmpty(keyValue)) {
            throw new DaoException("key value cannot be null");
        }
        map.put(DaoConst.KEY_VALUE, keyValue);
        map.put(DaoConst.FIELD, DaoConst.ASTERISK);
        setEnableFlag(map, true);
        return dataMapper.selectByKey(map);
    }

    public List<Map<String, Object>> selectByKeyList(List<? extends Object> list) {
        List<? extends Object> tempList = Linq4j.asEnumerable(list).where(p -> !ObjectUtils.isEmpty(p)).distinct()
                .toList();
        if (CollectionUtils.isEmpty(tempList)) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<Object> unCachedKeyValueList = new ArrayList<>();
        // 优先从缓存取数据
        if (enableCache) {
            resultList = dataCache.getTableListByKeyValueList(tempList, unCachedKeyValueList, tableName, keyField);
            DaoSourceContextHolder.setCacheCount(resultList.size());
            if (CollectionUtils.isEmpty(unCachedKeyValueList)) {
                return convertList(resultList);
            }
        } else {
            unCachedKeyValueList.addAll(tempList);
        }
        List<Map<String, Object>> dbList = selectByFieldList(unCachedKeyValueList, keyField, FilterPlus.build(), "");
        if (enableCache && !CollectionUtils.isEmpty(dbList)) {
            // 写入缓存
            dataCache.setTableList(dbList, tableName, keyField, expireTime);
        }
        DaoSourceContextHolder.setDbCount(dbList.size());
        resultList.addAll(dbList);
        return convertList(resultList);
    }

    <V> List<Map<String, Object>> selectByFieldList(List<V> list, String fieldName, FilterPlus filterPlus, String sort,
            String... params) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<V> tempList = Linq4j.asEnumerable(list).where(p -> !ObjectUtils.isEmpty(p)).distinct().toList();
        if (CollectionUtils.isEmpty(tempList)) {
            return new ArrayList<>();
        }
        if (!StringUtils.hasLength(fieldName)) {
            throw new DaoException("field name can not be null");
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        // 从缓存获取数据,主键会独立缓存，无需重复缓存
        boolean blCache = !keyField.equalsIgnoreCase(fieldName) && enableCache;
        String filter = filterPlus.getFilter();
        if (blCache) {
            List<Object> unCachedKeyValueList = new ArrayList<>();
            resultList = dataCache.getTableListByFieldList(fieldName, filter, sort, tempList,
                    unCachedKeyValueList, tableName, keyField);
            // 根据缓存没有的主键重新查询
            if (!CollectionUtils.isEmpty(unCachedKeyValueList)) {
                resultList.addAll(selectByKeyList(unCachedKeyValueList));
            }
            DaoSourceContextHolder.setCacheCount(resultList.size());
            removeCachedData(resultList, tempList, fieldName);
            if (CollectionUtils.isEmpty(tempList)) {
                return convertList(resultList);
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, DaoConst.ASTERISK);
        map.put(DaoConst.FIELD_NAME, fieldName);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        map.put(DaoConst.SORT, sort);
        setEnableFlag(map, true);
        // 每次查询的个数最大为500个
        int length = tempList.size();
        int num = length / DaoConst.IN_MAX_SIZE;
        int left = length % DaoConst.IN_MAX_SIZE;
        num = left > 0 ? num + 1 : num;
        List<Map<String, Object>> dbList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            List<V> subList = CommonUtils.getSubList(tempList, DaoConst.IN_MAX_SIZE, i);
            map.put(DaoConst.FIELD_VALUE_LIST, subList);
            List<Map<String, Object>> mapResult = dataMapper.selectByFieldList(map);
            dbList.addAll(mapResult);
        }
        // 写入缓存
        if (blCache) {
            dataCache.setTableListByField(fieldName, filter, sort, dbList, tableName, keyField, expireTimeList,
                    params);
        }
        DaoSourceContextHolder.setDbCount(dbList.size());
        resultList.addAll(dbList);
        return convertList(resultList);
    }

    private <V> void removeCachedData(List<Map<String, Object>> resultList, List<V> tempList, String fieldName) {
        if (CollectionUtils.isEmpty(tempList)) {
            return;
        }
        List<String> strList = tempList.stream().map(String::valueOf).collect(Collectors.toList());
        List<String> resultStrList = resultList.stream().map(p -> String.valueOf(p.get(fieldName))).distinct()
                .collect(Collectors.toList());
        for (String result : resultStrList) {
            int index = strList.indexOf(result);
            if (index > -1) {
                tempList.remove(index);
                strList.remove(index);
            }
        }
    }

    public List<Map<String, Object>> selectByMultiFieldList(List<LinkedHashMap<String, Object>> list, FilterPlus filterPlus, String sort,
            String... params) {
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<LinkedHashMap<String, Object>> tempList = Linq4j.asEnumerable(list).where(p -> !ObjectUtils.isEmpty(p))
                .distinct().toList();
        if (CollectionUtils.isEmpty(tempList)) {
            return new ArrayList<>();
        }
        Set<String> fieldSet = tempList.get(0).keySet();
        String multiFieldName = StringUtils.collectionToCommaDelimitedString(fieldSet);
        List<Map<String, Object>> resultList = new ArrayList<>();
        // 从缓存获取数据,主键会独立缓存，无需重复缓存
        String filter = filterPlus.getFilter();
        if (enableCache) {
            resultList = getTableListByMultiFieldListFromCache(tempList, filter, sort, multiFieldName);
            DaoSourceContextHolder.setCacheCount(resultList.size());
            if (CollectionUtils.isEmpty(tempList)) {
                return convertList(resultList);
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, DaoConst.ASTERISK);
        map.put(DaoConst.FIELD_NAME, String.format("(%s)", multiFieldName));
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        map.put(DaoConst.SORT, sort);
        setEnableFlag(map, true);
        // 每次查询的个数最大为500个
        int length = tempList.size();
        int num = length / DaoConst.IN_MAX_SIZE;
        int left = length % DaoConst.IN_MAX_SIZE;
        num = left > 0 ? num + 1 : num;
        List<Map<String, Object>> dbList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            List<LinkedHashMap<String, Object>> subList = CommonUtils.getSubList(tempList, DaoConst.IN_MAX_SIZE, i);
            map.put(DaoConst.MULTI_FIELD_VALUE_LIST, subList);
            List<Map<String, Object>> mapResult = dataMapper.selectByFieldList(map);
            dbList.addAll(mapResult);
        }
        // 写入缓存
        if (enableCache) {
            dataCache.setTableListByMultiField(multiFieldName, filter, sort, dbList, tableName, keyField,
                    expireTimeList, params);
        }
        DaoSourceContextHolder.setDbCount(dbList.size());
        resultList.addAll(dbList);
        return convertList(resultList);
    }

    private List<Map<String, Object>> getTableListByMultiFieldListFromCache(List<LinkedHashMap<String, Object>> list,
            String filter, String sort, String multiFieldName) {
        List<Object> unCachedKeyValueList = new ArrayList<>();
        List<Map<String, Object>> resultList = dataCache.getTableListByMultiFieldList(multiFieldName, filter,
                sort, list, unCachedKeyValueList, tableName, keyField);
        List<Map<String, Object>> fieldValueList = Linq4j.asEnumerable(resultList).select(p -> {
            Map<String, Object> map = new LinkedHashMap<>();
            for (String field : multiFieldName.split(DaoConst.SPLIT_COMMA)) {
                Object val = p.get(field);
                if (val != null) {
                    map.put(field, val);
                }
            }
            return map;
        }).distinct().toList();
        // 根据缓存没有的主键重新查询
        if (!CollectionUtils.isEmpty(unCachedKeyValueList)) {
            resultList.addAll(selectByKeyList(unCachedKeyValueList));
        }
        removeCacheFieldValue(list, fieldValueList);
        return resultList;
    }

    private void removeCacheFieldValue(List<LinkedHashMap<String, Object>> list,
            List<Map<String, Object>> fieldValueList) {
        for (int i = list.size() - 1; i >= 0; i--) {
            LinkedHashMap<String, Object> map = list.get(i);
            int count = Linq4j.asEnumerable(fieldValueList).count(p -> {
                Set<String> keys = map.keySet();
                for (String key : keys) {
                    boolean bl = map.get(key) != null && p.get(key) != null
                            && map.get(key).toString().equals(p.get(key).toString());
                    if (!bl) {
                        return false;
                    }
                }
                return true;
            });
            if (count > 0) {
                list.remove(map);
            }
        }
    }

    List<Map<String, Object>> select(FilterPlus filterPlus, String sort, Long page, Long rows, QueryModeEnum queryMode,
            String... params) {
        List<Map<String, Object>> list = null;
        // 如果启用缓存，从缓存取数据
        String filter = filterPlus.getFilter();
        // 查询模式：如果rows<=100使用默认查询
        if (rows == null || rows <= 100) {
            queryMode = QueryModeEnum.DEFAULT;
        }
        boolean defaultQueryMode = QueryModeEnum.DEFAULT.equals(queryMode);
        boolean needCache = enableCache && defaultQueryMode;
        // 如果启用缓存，从缓存取数据；如果使用流式查询和游标查询，不使用缓存
        if (needCache) {
            List<Object> unCachedKeyValueList = new ArrayList<>();
            list = dataCache.getTableList(filter, sort, page, rows, unCachedKeyValueList, tableName, keyField);
            // 根据缓存没有的主键重新查询
            if (!CollectionUtils.isEmpty(unCachedKeyValueList)) {
                list.addAll(selectByKeyList(unCachedKeyValueList));
            }
            if (!CollectionUtils.isEmpty(list)) {
                DaoSourceContextHolder.setCacheCount(list.size());
                return convertList(list);
            }
        }
        if (defaultQueryMode) {
            list = select(tableName, filterPlus, sort, page, rows);
        } else {
            list = selectByMode(tableName, filterPlus, sort, page, rows, queryMode);
        }
        // 如果启用缓存，设置缓存数据
        if (needCache) {
            dataCache.setTableList(filter, sort, page, rows, list, expireTimeList, tableName, keyField, params);
        }
        DaoSourceContextHolder.setDbCount(list.size());
        return convertList(list);
    }

    private List<Map<String, Object>> select(String tableName, FilterPlus filterPlus, String sort, Long page,
            Long rows) {
        Map<String, Object> map = getQueryMap(tableName, filterPlus, sort, page, rows);
        return dataMapper.select(map);
    }

    private Map<String, Object> getQueryMap(String tableName, FilterPlus filterPlus, String sort, Long page,
            Long rows) {
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.DB_TYPE, daoConfig.getDbType());
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, DaoConst.ASTERISK);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        map.put(DaoConst.SORT, sort);
        if (page == null) {
            page = 1L;
        }
        if (rows == null) {
            rows = 10L;
        }
        Long start = (page - 1) * rows;
        map.put(DaoConst.START, start);
        map.put(DaoConst.ROWS, rows);
        map.put(DaoConst.END, start + rows);
        setEnableFlag(map, true);
        return map;
    }

    private List<Map<String, Object>> selectByMode(String tableName, FilterPlus filterPlus, String sort, Long page,
            Long rows, QueryModeEnum queryMode) {
        Map<String, Object> map = getQueryMap(tableName, filterPlus, sort, page, rows);
        Cursor<Map<String, Object>> cursor = null;
        try {
            switch (queryMode) {
            case STREAMING:
                cursor = dataMapper.selectStreaming(map);
                break;
            case CURSOR:
                cursor = dataMapper.selectCursor(map);
                break;
            default:
                return Collections.emptyList();
            }
            List<Map<String, Object>> list = new ArrayList<>();
            Iterator<Map<String, Object>> iterator = cursor.iterator();
            while (iterator.hasNext()) {
                Map<String, Object> resultMap = iterator.next();
                list.add(resultMap);
            }
            return list;
        } finally {
            if (cursor != null) {
                try {
                    cursor.close();
                } catch (IOException e) {
                    LogUtils.logException(e);
                }
            }
        }
    }

    Long selectCount(FilterPlus filterPlus, String field, String... params) {
        String filter = filterPlus.getFilter();
        if (enableCache) {
            Long count = dataCache.getTableCount(filter, field, tableName);
            if (count > 0) {
                DaoSourceContextHolder.setDaoSource(DataSourceEnum.CACHE.getSource());
                return count;
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, field);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        setEnableFlag(map, true);
        Long count = dataMapper.selectCount(map);
        if (count > 0 && enableCache) {
            dataCache.setTableCount(filter, field, count, tableName, expireTimeList, params);
        }
        DaoSourceContextHolder.setDaoSource(DataSourceEnum.DB.getSource());
        return count;
    }

    PageRows<Map<String, Object>> selectPage(FilterPlus filterPlus, String sort, Long page, Long rows,
            QueryModeEnum queryMode, String... params) {
        List<Map<String, Object>> list = select(filterPlus, sort, page, rows, queryMode, params);
        Long count = selectCount(filterPlus, null, params);
        PageRows<Map<String, Object>> pageRows = new PageRows<>();
        page = (page == null || page <= 0) ? 1L : page;
        pageRows.setCurrent(page);
        pageRows.setTotal(count);
        pageRows.setRows(list);
        return pageRows;
    }

    List<Map<String, Object>> selectGroup(FilterPlus filterPlus, String field, String group, String sort, Long page, Long rows,
            String... params) {
        if (!StringUtils.hasLength(field) || !StringUtils.hasLength(group)) {
            throw new DaoException("field or group cannot be empty");
        }
        // 如果启用缓存，从缓存取数据
        String filter = filterPlus.getFilter();
        if (enableCache) {
            List<Map<String, Object>> list = dataCache.getTableGroupList(filter, field, group, sort, page, rows, tableName);
            if (!CollectionUtils.isEmpty(list)) {
                DaoSourceContextHolder.setDaoSource(DataSourceEnum.CACHE.getSource());
                return list;
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.DB_TYPE, daoConfig.getDbType());
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, field);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        map.put(DaoConst.GROUP, group);
        map.put(DaoConst.SORT, sort);
        if (page == null) {
            page = 1L;
        }
        if (rows == null) {
            rows = 10L;
        }
        Long start = (page - 1) * rows;
        map.put(DaoConst.START, start);
        map.put(DaoConst.ROWS, rows);
        setEnableFlag(map, true);
        List<Map<String, Object>> mapResult = dataMapper.selectGroup(map);
        if (!CollectionUtils.isEmpty(mapResult) && enableCache) {
            dataCache.setTableGroupList(filter, field, group, sort, page, rows, mapResult, tableName, expireTimeList,
                    params);
        }
        DaoSourceContextHolder.setDaoSource(DataSourceEnum.DB.getSource());
        return mapResult;
    }

    private <V> V selectAggregate(FilterPlus filterPlus, String aggregate, String field, Class<V> clazzV,
            String... params) {
        if (!StringUtils.hasLength(field)) {
            throw new DaoException(DaoConst.FIELD_CAN_NOT_BE_EMPTY);
        }
        String filter = filterPlus.getFilter();
        if (enableCache) {
            V v = dataCache.getTableAggregate(filter, aggregate, field, tableName, clazzV);
            if (v != null) {
                DaoSourceContextHolder.setDaoSource(DataSourceEnum.CACHE.getSource());
                return v;
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.AGGREGATE, aggregate);
        map.put(DaoConst.FIELD, field);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        setEnableFlag(map, true);
        Object obj = dataMapper.selectAggregate(map);
        V v = clazzV.cast(obj);
        if (v != null && enableCache) {
            dataCache.setTableAggregate(filter, aggregate, field, v, tableName, expireTimeList, params);
        }
        DaoSourceContextHolder.setDaoSource(DataSourceEnum.DB.getSource());
        return v;
    }

    <V> V selectMax(FilterPlus filterPlus, String field, Class<V> clazzV, String... params) {
        return selectAggregate(filterPlus, DaoConst.MAX, field, clazzV, params);
    }

    <V> V selectMin(FilterPlus filterPlus, String field, Class<V> clazzV, String... params) {
        return selectAggregate(filterPlus, DaoConst.MIN, field, clazzV, params);
    }

    <V> V selectSum(FilterPlus filterPlus, String field, Class<V> clazzV, String... params) {
        return selectAggregate(filterPlus, DaoConst.SUM, field, clazzV, params);
    }

    <V> List<V> selectDistinct(FilterPlus filterPlus, String field, Class<V> clazzV, String... params) {
        if (!StringUtils.hasLength(field)) {
            throw new DaoException(DaoConst.FIELD_CAN_NOT_BE_EMPTY);
        }
        String[] arr = field.split(DaoConst.COMMA);
        filterPlus.addBrackets().add(p -> {
            for (int i = 0; i < arr.length; i++) {
                p.addIsNotNull(arr[i]);
            }
        });
        String filter = filterPlus.getFilter();
        if (enableCache) {
            List<V> list = dataCache.getTableDistinct(filter, field, tableName);
            if (!CollectionUtils.isEmpty(list)) {
                DaoSourceContextHolder.setDaoSource(DataSourceEnum.CACHE.getSource());
                return list;
            }
        }
        Map<String, Object> map = filterPlus.getParamMap();
        map.put(DaoConst.TABLE_NAME, tableName);
        map.put(DaoConst.FIELD, field);
        map.put(DaoConst.FILTER, filterPlus.getParamFilter());
        setEnableFlag(map, true);
        List<Object> list = dataMapper.selectDistinct(map);
        List<V> resultList = Linq4j.asEnumerable(list).select(clazzV::cast).toList();
        if (!CollectionUtils.isEmpty(resultList) && enableCache) {
            dataCache.setTableDistinct(filter, field, resultList, tableName, expireTimeList, params);
        }
        DaoSourceContextHolder.setDaoSource(DataSourceEnum.DB.getSource());
        return resultList;
    }
    
    private Map<String, Object> convertMap(Map<String, Object> map) {
        if (!StringUtils.hasLength(selectFields)) {
            return map;
        }
        Map<String, Object> resultMap = new HashMap<>(16);
        for (String selectField : selectFields.split(DaoConst.COMMA)) {
            String fieldName = selectField.trim();
            if (map.containsKey(fieldName)) {
                resultMap.put(fieldName, map.get(fieldName));
            }
        }
        return resultMap;
    }
    
    private List<Map<String, Object>> convertList(List<Map<String, Object>> list) {
        if (!StringUtils.hasLength(selectFields)) {
            return list;
        }
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map<String, Object> map : list) {
            resultList.add(convertMap(map));
        }
        return resultList;
    }
}
